﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Collections;
using System.Xml.Serialization;
using System.Xml;
using System.IO;
using CRMAdminDashboard.CrmSvc;

namespace CRMAdminDashboard
{
    /// <summary>
    /// Wrapper for CrmSvc.systemuser.
    /// </summary>
    public class SystemUser
    {

        #region Properties

        /// <summary>
        /// User's Guid in CRM.
        /// </summary>
        public Guid Id { get; set; }

        /// <summary>
        /// User's FullName in CRM.
        /// </summary>
        public string FullName { get; set; }

        /// <summary>
        /// User's Business Unit Name in CRM.
        /// </summary>
        public string BusinessUnitName { get; set; }

        /// <summary>
        /// User's Business Unit Id in CRM.
        /// </summary>
        public Guid BusinessUnitId { get; set; }

        /// <summary>
        /// User's Domain Name in CRM.
        /// </summary>
        public string DomainName { get; set; }

        /// <summary>
        /// Minimum set of attributes to query.
        /// </summary>
        static public ColumnSet SystemUserColumnSet { get; set; }

        /// <summary>
        /// The actual CRM object.
        /// </summary>
        public systemuser InnerUser { get; set; }

        #endregion

        #region Entry Points

        /// <summary>
        /// Standard ctor.
        /// </summary>
        public SystemUser(systemuser crmUser)
        {
            this.InnerUser = crmUser;
            this.FullName = crmUser.fullname;
            this.BusinessUnitName = crmUser.businessunitid.name;
            this.BusinessUnitId = crmUser.businessunitid.Value;
            this.DomainName = crmUser.domainname;
            this.Id = crmUser.systemuserid.Value;
        }

        /// <summary>
        /// This will make the list box entry look nice
        /// </summary>
        public override string ToString()
        {
            if (this.InnerUser.accessmode.name != "Full")
            {
                return this.InnerUser.accessmode.name + ": [" + this.BusinessUnitName + "] " + this.FullName + " (" + this.DomainName + ")";
            }
            else
            {
                return "[" + this.BusinessUnitName + "] " + this.FullName + " (" + this.DomainName + ")";
            }
        }

        /// <summary>
        /// Shorter version of Tostring()
        /// </summary>
        public string ToStringShort()
        {
            return "[" + this.BusinessUnitName + "] " + this.FullName;
        }

        /// <summary>
        /// Return all the security roles this user has
        /// </summary>
        public Dictionary<Guid, SystemRole> GetRoles(CachingCrmService svcHandle, ColumnSetBase columns)
        {
            List<role> roles = GetRolesInternal(svcHandle, columns);

            Dictionary<Guid, SystemRole> list = new Dictionary<Guid, SystemRole>();
            foreach (role role in roles)
            {
                list.Add(role.roleid.Value, new SystemRole(role, svcHandle));
            }

            return list;
        }

        /// <summary>
        /// Return all the security roles this user has, but instead of returning the actual roles return
        /// the root ones, according to rUHierarchy
        /// </summary>
        public Dictionary<Guid, SystemRole> GetRootRoles(CachingCrmService svcHandle, RoleUserHierarchy rUHierarchy)
        {
            // get all the roles
            List<role> roles = GetRolesInternal(svcHandle, SystemRole.SystemRoleColumnSet);

            // just return the pointers in the role collection
            Dictionary<Guid, SystemRole> list = new Dictionary<Guid, SystemRole>();
            foreach (role role in roles)
            {
                SystemRole root = rUHierarchy.AllRoles[role.roleid.Value].RootRole;
                list.Add(root.Id, root);
            }

            return list;
        }

        /// <summary>
        /// Get all system users.
        /// </summary>
        public static Dictionary<Guid, SystemUser> GetAllUsers(CachingCrmService svcHandle, ColumnSetBase columns)
        {
            // get all users
            QueryByAttribute query = new QueryByAttribute();
            query.EntityName = EntityName.systemuser.ToString();
            query.ColumnSet = columns;
            // only active users
            query.Attributes = new string[] { "isdisabled", "setupuser" };
            query.Values = new object[] { false, false };

            BusinessEntityCollection users = svcHandle.RetrieveMultiple(query);
            Dictionary<Guid, SystemUser> list = new Dictionary<Guid, SystemUser>();
            foreach (BusinessEntity be in users.BusinessEntities)
            {
                systemuser user = (systemuser)be;
                if (user.domainname != null)
                {
                    // we only load "proper" users
                    list.Add(user.systemuserid.Value, new SystemUser(user));
                }
            }

            return list;
        }

        #endregion

        #region Local Methods

        /// <summary>
        /// Static initializer
        /// </summary>
        static SystemUser()
        {
            SystemUserColumnSet = new ColumnSet();
            SystemUserColumnSet.Attributes = new string[] { "businessunitid", "fullname", "domainname", "accessmode" };
        }

        /// <summary>
        /// Return all the security roles this user has as a list of <role>
        /// </summary>
        private List<role> GetRolesInternal(CachingCrmService svcHandle, ColumnSetBase columns)
        {
            ConditionExpression condition = new ConditionExpression();
            condition.AttributeName = "systemuserid";
            condition.Operator = ConditionOperator.Equal;
            condition.Values = new object[] { this.Id };

            LinkEntity link = new LinkEntity();
            link.LinkFromEntityName = EntityName.role.ToString();
            link.LinkFromAttributeName = "roleid";
            link.LinkToEntityName = "systemuserroles";
            link.LinkToAttributeName = "roleid";
            link.LinkCriteria = new FilterExpression();
            link.LinkCriteria.Conditions = new ConditionExpression[] { condition };

            QueryExpression query = new QueryExpression();
            query.EntityName = EntityName.role.ToString();
            query.LinkEntities = new LinkEntity[] { link };
            query.ColumnSet = columns;

            RetrieveMultipleRequest retrieveRequest = new RetrieveMultipleRequest();
            retrieveRequest.Query = query;
            RetrieveMultipleResponse retrieveResponse = (RetrieveMultipleResponse)svcHandle.Execute(retrieveRequest);

            List<role> list = new List<role>();
            foreach (BusinessEntity be in retrieveResponse.BusinessEntityCollection.BusinessEntities)
            {
                list.Add((role)be);
            }

            return list;
        }

        #endregion

    }
}
